package com.zhdl.common.util;

import cn.hutool.core.util.HexUtil;

import java.nio.ByteBuffer;
import java.util.LinkedList;

/**
 * 字节处理类
 */
public class ByteUtil {

    /**
     * DIGITAL
     */
    public static final String DIGITAL = "0123456789ABCDEF";

    /**
     * 16进制表示符
     */
    public static final String HEX = "0x";

    /**
     * 字节数组转16进制字符串 0x1234转换为字符串1234
     *
     * @param b 字节数组
     * @return 16进制字符串
     */
    public static String byteToString(byte b) {
        StringBuilder sbf = new StringBuilder();
        String hex = Integer.toHexString(b);
        if (hex.length() == 1) {
            hex = '0' + hex;
        }
        sbf.append(hex.toUpperCase()).append(" ");
        return sbf.toString().trim();
    }

    /**
     * 字节转换为 16 进制字符串
     *
     * @param b
     * @return
     */
    public static String byteToHexStr(byte b) {
        char[] hexChars = new char[2];
        hexChars[0] = Character.forDigit((b >> 4) & 0xF, 16);
        hexChars[1] = Character.forDigit((b & 0xF), 16);
        return new String(hexChars).toUpperCase();
    }

    /**
     * 字节数组转换为二进制字符串
     *
     * @param bytes
     * @return
     */
    public static String bytesToBinaryString(byte[] bytes) {
        StringBuilder binaryStringBuilder = new StringBuilder();
        for (byte b : bytes) {
            int x = b;
            if (x < 0) {
                x += 256;
            }
            String binaryString = Integer.toBinaryString(x);
            while (binaryString.length() < 8) {
                binaryString = "0" + binaryString;
            }
            binaryStringBuilder.append(binaryString);
        }
        return binaryStringBuilder.toString();
    }

    /**
     * 将字节数组倒序排列后转为二进制字符串
     *
     * @param byteArray
     * @return
     */
    public static String reverseByteArrayToBinaryString(byte[] byteArray) {
        // reverse the order of bytes in the array
        byte[] reversedArray = new byte[byteArray.length];
        for (int i = 0; i < byteArray.length; i++) {
            reversedArray[i] = byteArray[byteArray.length - i - 1];
        }
        // convert reversed array to binary String
        StringBuilder binaryString = new StringBuilder();
        for (byte b : reversedArray) {
            binaryString.append(String.format("%8s", Integer.toBinaryString(b & 0xFF)).replace(' ', '0'));
        }
        return binaryString.toString();
    }

    /**
     * 将字节数组以2个为一组进行交换后转换为10进制取绝对值
     *
     * @param bytes
     * @return
     */
    public static LinkedList<Integer> byteToAbsDecimalList(byte[] bytes) {
        LinkedList<Integer> decimalList = new LinkedList<>();
        for (int i = 0; i < bytes.length; i += 2) {
            // 将每2个字节进行高低位交换，转换成short型数据
            short decimal = ByteBuffer.wrap(new byte[]{bytes[i + 1], bytes[i]}).getShort();
            // 求绝对值
            decimalList.add(Math.abs(decimal));
        }
        return decimalList;
    }

    public static LinkedList<Integer> byteArrayToList(byte[] array) {
        LinkedList<Integer> list = new LinkedList<>();
        for (byte b : array) {
            list.add((int) b & 0xFF);
        }
        return list;
    }

    /**
     * 该方法接收一个十六进制字符串作为参数，并返回这个十六进制字符串对应的二进制字符串
     *
     * @param hexString
     * @return
     */
    public static String hexStringToBinaryString(String hexString) {
        if (hexString == null || hexString.length() % 2 != 0) {
            return null;
        }
        StringBuilder binaryStringBuilder = new StringBuilder();
        for (int i = 0; i < hexString.length(); i += 2) {
            String hex = hexString.substring(i, i + 2);
            int decimal = Integer.parseInt(hex, 16);
            String binary = Integer.toBinaryString(decimal);
            binary = String.format("%4s", binary).replace(' ', '0');
            binaryStringBuilder.append(binary);
        }
        return binaryStringBuilder.toString();
    }


    /**
     * 字节数组转16进制字符串 0x1234转换为字符串12 34，中间有空格
     *
     * @param b 字节数组
     * @return 16进制字符串
     */
    public static String byteToString(byte[] b) {
        StringBuilder sbf = new StringBuilder();
        for (byte value : b) {
            String hex = Integer.toHexString(value & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sbf.append(hex.toUpperCase()).append(" ");
        }
        return sbf.toString().trim();
    }


    /**
     * 16进制字符串转字节数组 字符串1234转换为0x1234
     *
     * @param hex 16进制字符串
     * @return 字节数组
     */
//    public static byte[] hex2byte(String hex) {
//        hex = hex.replace(" ", "");
//
//        if (!isHexString(hex)) {
//            return null;
//        }
//
//        char[] arr = hex.toCharArray();
//        byte[] b = new byte[hex.length() / 2];
//        for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) {
//            String swap = "" + arr[i++] + arr[i];
//            Integer byteint = Integer.parseInt(swap, 16) & 0xFF;
//            b[j] = byteint.byteValue();
//        }
//        return b;
//    }

    /**
     * 16进制字符串转字节数组 字符串1234转换为0x1234
     *
     * @param hex 16进制字符串
     * @return 字节数组
     */
    public static byte[] hex2byte(String hex) {
        if (hex == null || hex.length() % 2 != 0) {
            return null;
        }

        hex = hex.toUpperCase();
        StringBuilder sb = new StringBuilder(hex);
        int len = sb.length() / 2;
        for (int i = 0; i < len; i++) {
            int index = i * 2;
            char c1 = sb.charAt(index);
            char c2 = sb.charAt(index + 1);
            if (!isHexChar(c1) || !isHexChar(c2)) {
                return null;
            }
            int b = (hexCharToInt(c1) << 4) | hexCharToInt(c2);
            sb.setCharAt(index, (char) b);
            sb.setCharAt(index + 1, (char) 0);
        }
        return sb.toString().getBytes();
    }

//    /**
//     * 判断字符是否为16进制字符
//     *
//     * @param c 字符
//     * @return 是否为16进制字符
//     */
//    private static boolean isHexChar(char c) {
//        return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F');
//    }

    /**
     * 将16进制字符转换为整数
     *
     * @param c 16进制字符
     * @return 整数
     */
    private static int hexCharToInt(char c) {
        if (c >= '0' && c <= '9') {
            return c - '0';
        } else {
            return c - 'A' + 10;
        }
    }

    /**
     * 校验是否是16进制字符串
     *
     * @param hex
     * @return
     */
    public static boolean isHexString(String hex) {
        if (hex == null || hex.length() % 2 != 0) {
            return false;
        }
        for (int i = 0; i < hex.length(); i++) {
            char c = hex.charAt(i);
            if (!isHexChar(c)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 校验是否是16进制字符
     *
     * @param c
     * @return
     */
    private static boolean isHexChar(char c) {
        return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
    }

    /**
     * 将short转为低字节在前，高字节在后的byte数组
     */
    public static byte[] shortToByteArrayByLow(short n) {
        byte[] bytes = new byte[2];
        bytes[0] = (byte) n; // 低字节在前
        bytes[1] = (byte) (n >> 8); // 高字节在后
        return bytes;
    }

    /**
     * 将short转为低字节在前，高字节在后的byte数组
     */
    public static byte[] shortToByteArrayByLow2(short n) {
        byte[] bytes = new byte[2];
        bytes[0] = (byte) (n & 0xff);
        bytes[1] = (byte) (n >>> 8 & 0xff);
        return bytes;
    }

    /**
     * 将short转为高字节在前，低字节在后的byte数组
     */
    public static byte[] shortToByteArrayByHigh(short n) {
        byte[] bytes = new byte[2];
        bytes[1] = (byte) (n & 0xff);
        bytes[0] = (byte) (n >>> 8 & 0xff);
        return bytes;
    }

    /**
     * byte数组转换为short，低字节在前
     *
     * @param bytes 2字节数组
     * @return 有符号short
     */
    public static short byteArrayToShortLow(byte[] bytes) {
        if (bytes.length != 2) {
            throw new RuntimeException("长度不正确");
        }

        return (short) ((bytes[0] & 0xff) | ((bytes[1] & 0xff) << 8));
    }

    /**
     * byte数组转换为short，高字节在前，低字节在后
     *
     * @param bytes 2字节数组
     * @return 有符号short
     */
    public static short byteArrayToShortHigh(byte[] bytes) {
        if (bytes.length != 2) {
            throw new RuntimeException("长度不正确");
        }
        byte[] bsTemp = new byte[2];
        bsTemp[0] = bytes[1];
        bsTemp[1] = bytes[0];
        return byteArrayToShortLow(bsTemp);
    }

    /**
     * 无符号int转换为byte[]，不考虑正负
     *
     * @param i
     * @return
     */
    public static byte[] uIntToByteArray(long i) {
        byte[] bytes = new byte[4];
        bytes[0] = (byte) i;
        bytes[1] = (byte) (i >> 8);
        bytes[2] = (byte) (i >> 16);
        bytes[3] = (byte) (i >> 24);
        return bytes;
    }

    /**
     * 字节数组转换为无符号号int
     *
     * @param bytes
     * @return
     */
    public static long byteArrayToUInt(byte[] bytes) {
        long res = 0;
        for (int i = 0; i < bytes.length; i++) {
            res += (bytes[i] & 0xff) << i * 8;
        }
        return res;
    }


    /**
     * 有符号int转换为byte[]，不考虑正负
     *
     * @param i
     * @return
     */
    public static byte[] IntToByteArray(long i) {
        byte[] bytes = new byte[4];
        bytes[0] = (byte) (i & 0xff);
        bytes[1] = (byte) (i >> 8 & 0xff);
        bytes[2] = (byte) (i >> 16 & 0xff);
        bytes[3] = (byte) (i >> 24 & 0xff);
        return bytes;
    }

    /**
     * 4字节数组byte[]转换为int，带符号
     *
     * @param bytes 4字节数组
     * @return
     */
    public static int byteArrayToInt(byte[] bytes) {
        return (bytes[0] & 0xff) + ((bytes[1] & 0xff) << 8) + ((bytes[2] & 0xff) << 16) + ((bytes[3] & 0xff) << 24);
    }

    /**
     * int转换为byte[]，不考虑正负，采用逆序转储
     *
     * @param i
     * @return
     */
    public static byte[] intToByteArrayReverse(int i) {
        byte[] b = new byte[4];
        b[0] = (byte) (i >> 24);
        b[1] = (byte) (i >> 16);
        b[2] = (byte) (i >> 8);
        b[3] = (byte) i;
        return b;
    }

    public static int byteArrayToIntReverse(byte[] bytes) {
        int value = 0;
        for (int i = 0; i < 4; i++) {
            value += (bytes[i] & 0xff) << (3 - i) * 8;
        }
        return value;
    }


    /**
     * 字节数组转换为16进制字符串
     *
     * @param src src
     * @return string string
     */
    public static String bytesArrayToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder();
        if (src == null || src.length <= 0) {
            return null;
        }
        for (byte b : src) {
            int v = b & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }

    /**
     * 16进制字符串转换为字节数组
     *
     * @param hex hex
     * @return byte [ ]
     * @since 1.0
     */
    public static byte[] stringToBytes(String hex) {
        String hex1 = hex.replace(" ", "");
        char[] hex2char = hex1.toCharArray();
        byte[] bytes = new byte[hex1.length() / 2];
        byte temp;
        for (int p = 0; p < bytes.length; p++) {
            temp = (byte) (DIGITAL.indexOf(hex2char[2 * p]) * 16);
            temp += DIGITAL.indexOf(hex2char[2 * p + 1]);
            bytes[p] = (byte) (temp & 0xff);
        }
        return bytes;
    }

    /**
     * 二进制字符串转字节，00000000 返回0x00
     *
     * @param bitStr
     * @return
     */
    public static byte bitString2Byte(String bitStr) {
        if (bitStr == null || bitStr.length() == 0) {
            return 0;
        }
        if (bitStr.length() != 8) {
            // 如果不足8位的，补足8位;超过8位，截取后8位
            String temp = ("00000000" + bitStr);
            bitStr = temp.substring(temp.length() - 8, 8);
        }

        byte rs;
        if (bitStr.charAt(0) == '0') {
            // 正数
            rs = Byte.parseByte(bitStr, 2);
        } else {
            //负数
            rs = (byte) (Integer.parseInt(bitStr, 2) - 256);
        }

        return rs;
    }

    /**
     * 字转转换为二进制字符串 0x64转换为01100100
     *
     * @param bt
     * @return
     */
    public static String byte2BitString(byte bt) {
        StringBuilder sb = new StringBuilder();
        sb.append((bt >> 7) & 0x1);
        sb.append((bt >> 6) & 0x1);
        sb.append((bt >> 5) & 0x1);
        sb.append((bt >> 4) & 0x1);
        sb.append((bt >> 3) & 0x1);
        sb.append((bt >> 2) & 0x1);
        sb.append((bt >> 1) & 0x1);
        sb.append((bt) & 0x1);
        return sb.toString();
    }

    /**
     * 字符串转16进制字符串
     *
     * @param strPart
     * @return
     */
    public static String string2HexString(String strPart) {
        StringBuffer hexString = new StringBuffer();
        for (int i = 0; i < strPart.length(); i++) {
            int ch = (int) strPart.charAt(i);
            String strHex = Integer.toHexString(ch);
            hexString.append(strHex);
        }
        return hexString.toString();
    }

    /**
     * 十六进制转字节数组
     *
     * @param src
     * @return
     */
    public static byte[] hexString2Bytes(String src) {
        int l = src.length() / 2;
        byte[] ret = new byte[l];
        for (int i = 0; i < l; i++) {
            ret[i] = (byte) Integer.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();
        }
        return ret;
    }

    /**
     * 字符串转换十六进制数组
     *
     * @param src
     * @return
     */
    public static byte[] stringToHexBytes(String src) {
        return HexUtil.decodeHex(src);
    }
}
